package com.whfc.mach.manager.util;

import com.whfc.mach.dto.AppMachOilLookup;
import com.whfc.mach.dto.Oil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 设备油位处理工具类
 * @author: xugcheng
 * @version: 1.0
 * @date: 2019/12/26 19:45
 */
public class MachOilUtil {

    private static Logger logger = LoggerFactory.getLogger(MachOilUtil.class);

    /**
     * 油位下降波动阈值(mm)
     */
    public static final double OIL_POS_DOWN_THRESHOLD = 50;

    /**
     * 最小加油阈值(mm)
     */
    public static final double MIN_OIL_ADD_THRESHOLD = 100;

    /**
     * 中值滤波参数(前m个和后m个,n=2m+1)
     */
    public static final int MED_FILT_M = 25;

    /**
     * 最小有效油位值
     */
    public static final int MIN_OIL_POS = 20;

    /**
     * 修正设备油位信息
     *
     * @param oilList
     * @param oilTankHeight
     * @return
     */
    public static List<Oil> amendMachOil(List<Oil> oilList, Double oilTankHeight) {

        //有效范围修正
        int maxValue = oilTankHeight != null ? oilTankHeight.intValue() * 10 : 0;
        int minValue = MIN_OIL_POS;

        //无效值过滤
        oilList = oilList.stream()
                .filter(oil -> isValidPos(oil.getOilPos(), maxValue, minValue))
                .collect(Collectors.toList());

        return oilList;
    }

    /**
     * 修正设备油位信息
     *
     * @param oilPos
     * @param oilTankHeight
     * @return
     */
    public static Integer amendMachOil(Integer oilPos, Double oilTankHeight) {

        //无效值过滤
        if (oilPos == null) {
            return 0;
        }

        //有效范围修正
        int maxValue = oilTankHeight != null ? oilTankHeight.intValue() * 10 : 0;
        int minValue = MIN_OIL_POS;
        oilPos = oilPos > maxValue ? maxValue :
                oilPos < minValue ? minValue : oilPos;
        return oilPos;
    }

    /**
     * 中值滤波
     *
     * @param oilList 数组
     * @param m       滤波参数(n=2m+1)
     * @return
     */
    public static List<Oil> medfilt(List<Oil> oilList, int m) {
        int n = 2 * m + 1;
        if (oilList.size() < n) {
            return oilList;
        }
        List<Integer> posList = new ArrayList<>(oilList.size());
        for (int i = 0; i < oilList.size(); i++) {
            List<Integer> tempList = new ArrayList<>(n);
            //开始m个数,前面补0
            if (i >= 0 && i < m) {
                for (int k = 0; k < m - i; k++) {
                    tempList.add(0);
                }
                for (int k = 0; k < i + m + 1; k++) {
                    tempList.add(oilList.get(k).getOilPos());
                }
            }
            //最后m个数,后面补0
            else if (i >= oilList.size() - m && i < oilList.size()) {
                for (int k = i - m; k < oilList.size(); k++) {
                    tempList.add(oilList.get(k).getOilPos());
                }
                for (int k = 0; k < (m - (oilList.size() - i - 1)); k++) {
                    tempList.add(0);
                }
            }
            //中间数处理
            else {
                for (int k = i - m; k < i + m + 1; k++) {
                    tempList.add(oilList.get(k).getOilPos());
                }
            }
            logger.debug("i={},{}", i, tempList);
            Collections.sort(tempList);
            posList.add(tempList.get(tempList.size() / 2));
        }
        for (int i = 0; i < oilList.size(); i++) {
            oilList.get(i).setOilPos(posList.get(i));
        }
        return oilList;
    }

    /**
     * 油箱盖状态:打开
     *
     * @param oilState
     * @return
     */
    public static boolean isOpen(Integer oilState) {
        return oilState != null && oilState == 1;
    }

    /**
     * 油箱盖状态:关闭
     *
     * @param oilState
     * @return
     */
    public static boolean isClose(Integer oilState) {
        return oilState != null && oilState == 2;
    }

    /**
     * 有效油位值
     *
     * @param oilPos
     * @return
     */
    public static boolean isValidPos(Integer oilPos, int maxValue, int minValue) {
        return oilPos != null && oilPos > minValue && oilPos < maxValue;
    }

    /**
     * 压力值转换油位高度
     *
     * @param pressure (kpa)
     * @return 毫米
     */
    public static Integer pressureToOilPos(Double pressure) {
        return pressure == null ? 0 : (int) (pressure * 845 / 9.8);
    }

    /**
     * 油位高度转换压力值
     *
     * @param oilPos
     * @return
     */
    public static Double oilPosToPressure(Integer oilPos) {
        return oilPos == null ? 0 : oilPos * 9.8 / 845;
    }

    /**
     * 查找容积
     *
     * @param lookup
     * @param oilPos
     * @return
     */
    public static Double getOilVolume(AppMachOilLookup lookup, Integer oilPos) {
        if (oilPos != null) {
            int key = oilPos;
            if (key < lookup.getMinPos()) {
                return lookup.getMinVolume();
            }
            if (key > lookup.getMaxPos()) {
                return lookup.getMaxVolume();
            }
            //有油位标定表
            Map<Integer, Double> oilSheetMap = lookup.getOilSheetMap();
            if (oilSheetMap != null && oilSheetMap.containsKey(key)) {
                Double value = oilSheetMap.get(key);
                if (value != null) {
                    return value;
                }
            }
        }
        return 0D;
    }
}
